﻿using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Config;
using UtilZ.Dotnet.Ex.Log;

namespace UtilZFileServer
{
    public class Config : IConfig
    {
        #region 单元实例
        private static Config _instance;
        public static Config Instance
        {
            get { return _instance; }
        }

        static Config()
        {
            _instance = Load();
        }
        #endregion



        #region 配置读写及初始化
        private const string _DEFAULT_CONFIGFILE_NAME = "config.xml";

        /// <summary>
        /// 加载配置
        /// </summary>
        /// <returns>配置对象</returns>
        private static Config Load()
        {
            Config config = new Config();
            if (File.Exists(_DEFAULT_CONFIGFILE_NAME))
            {
                try
                {
                    ConfigHelper.ReadConfigFromFile(_DEFAULT_CONFIGFILE_NAME, config);
                }
                catch (Exception ex)
                {
                    Loger.Error(ex);
                    config.InitDefaultValue();
                    SerializeToFile(config, _DEFAULT_CONFIGFILE_NAME);
                }
            }
            else
            {
                config.InitDefaultValue();
                SerializeToFile(config, _DEFAULT_CONFIGFILE_NAME);
            }

            return config;
        }

        private static void SerializeToFile(Config config, string configFilePath)
        {
            DirectoryInfoEx.CheckFilePathDirectory(configFilePath);
            ConfigHelper.WriteConfigToXmlFile(config, configFilePath);
        }

        /// <summary>
        /// 保存配置
        /// </summary>
        public void Save()
        {
            SerializeToFile(this, _DEFAULT_CONFIGFILE_NAME);
        }



        /// <summary>
        /// 
        /// </summary>
        public void InitDefaultValue()
        {
            this.PassiveIgnorePortList = new List<ushort>() { 54001 };

            this._localPaths.Add(new PathItem("Soft", @"E:\Soft"));
            this._localPaths.Add(new PathItem("OSM", @"D:\osm"));

            this._toolLocalPaths.Add(new PathItem("FileZilla_3.58.0_win32.zip", @"D:\Soft\FileZilla\FTPClients\FileZilla_3.58.0_win32.zip"));
            this._toolLocalPaths.Add(new PathItem("FileZilla_3.58.0_x86_64-linux-gnu.tar.bz2", @"D:\Soft\FileZilla\FTPClients\FileZilla_3.58.0_x86_64-linux-gnu.tar.bz2"));

        }
        #endregion


        /// <summary>
        /// 服务名称
        /// </summary>
        [ConfigItem("ServiceName", "最大连接数,小于0无限制", Order = 1)]
        public string ServiceName { get; set; } = "UtilZFileServer";

        /// <summary>
        /// 显示进程窗口[true:显示;false:隐藏]
        /// </summary>
        [ConfigItem("ShowProcessWindow", "显示进程窗口[true:显示;false:隐藏]", Order = 2)]
        public bool ShowProcessWindow { get; set; } = true;

        /// <summary>
        /// 最大连接数,小于0无限制
        /// </summary>
        [ConfigItem("MaxConnections", "最大连接数,小于0无限制", Order = 10)]
        public int MaxConnections { get; set; } = 1000;

        /// <summary>
        /// http端口,小于等于0不启用
        /// </summary>
        [ConfigItem("HttpPort", "http端口,小于等于0不启用", Order = 11)]
        public int HttpPort { get; set; } = 54001;

        private readonly List<PathItem> _localPaths = new List<PathItem>();
        /// <summary>
        /// 本地路径集合
        /// </summary>
        [ConfigCollection("LocalPaths", "LocalPath", "本地路径集合", true, Order = 12)]
        public List<PathItem> LocalPaths
        {
            get { return this._localPaths; }
        }

        private readonly List<PathItem> _toolLocalPaths = new List<PathItem>();
        /// <summary>
        /// 本地工具路径集合
        /// </summary>
        [ConfigCollection("ToolLocalPaths", "ToolLocalPath", "本地工具路径集合", true, Order = 13)]
        public List<PathItem> ToolLocalPaths
        {
            get { return this._toolLocalPaths; }
        }



        /// <summary>
        /// ftp命令端口,小于等于0不启用
        /// </summary>
        [ConfigItem("FtpCommandPort", "ftp命令端口,小于等于0不启用", Order = 31)]
        public int FtpCommandPort { get; set; } = 21;

        /// <summary>
        /// ftp主动模式(Port-Standard)端口,默认20.小于0由操作系统指定
        /// </summary>
        [ConfigItem("PortModePort", "ftp主动模式(Port-Standard)端口,默认20.小于0由操作系统指定", Order = 32)]
        public ushort PortModePort { get; set; } = 20;

        /// <summary>
        /// ftp被动模式(Passive)端口范围最小值,需要大于1024,默认20000
        /// </summary>
        [ConfigItem("PassiveMinPort", "ftp被动模式(Passive)端口范围最小值,需要大于1024,默认20000", Order = 33)]
        public ushort PassiveMinPort { get; set; } = 20000;

        /// <summary>
        /// ftp被动模式(Passive)端口范围最大值,需要大于最小值,默认40000
        /// </summary>
        [ConfigItem("PassiveMaxPort", "ftp被动模式(Passive)端口范围最大值,需要大于最小值,默认40000", Order = 34)]
        public ushort PassiveMaxPort { get; set; } = 40000;

        /// <summary>
        /// ftp被动模式(Passive)忽略的端口列表
        /// </summary>
        [ConfigCollection("PassiveIgnorePortList", "Port", "ftp被动模式(Passive)忽略的端口列表", true, Order = 35)]
        public List<ushort> PassiveIgnorePortList { get; set; }

    }

    /// <summary>
    /// 路径信息
    /// </summary>
    public class PathItem
    {
        /// <summary>
        /// 路径别名
        /// </summary>
        [ConfigItem("Alias", "路径别名")]
        public string Alias { get; set; }

        /// <summary>
        /// 路径
        /// </summary>
        [ConfigItem("Path", "路径")]
        public string Path { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="alias"></param>
        /// <param name="path"></param>
        public PathItem(string alias, string path)
        {
            this.Alias = alias;
            this.Path = path;
        }

        /// <summary>
        /// 
        /// </summary>
        public PathItem()
        {

        }
    }
}
